﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.Common;
using Microsoft.VisualStudio.TestTools.Vsip;
using TLM.VsmdiReader;

namespace TLM.TestCategoryGenerator
{
    public class Generator
    {
        private ITestManagement _tmiInstance;
        private ITuip _unitTestService;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="tmiInstance">The TMI instance of the project</param>
        /// <param name="unitTestService">The test user interface instance of the project</param>
        public Generator(ITestManagement tmiInstance, ITuip unitTestService)
        {
            _tmiInstance = tmiInstance;
            _unitTestService = unitTestService;
        }

        /// <summary>
        /// Add the TestCategory Attribute to all the enabled testlinks is all enabled testLists
        /// </summary>
        /// <param name="vsmdiObject"></param>
        public void AddTestCategories(VsmdiFile vsmdiObject)
        {
            if (vsmdiObject == null)
            {
                throw new ArgumentNullException("vsmdiObject");
            }

            // Recursively convert and save all child lists
            AddCategoriesToChildPlaylists(Enumerable.Repeat(vsmdiObject.ListOfTests, 1), null);

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="childTestLits">A collection test lists</param>
        /// <param name="currentTestListPath">The current test list path wich contains all parents</param>
        private void AddCategoriesToChildPlaylists(IEnumerable<TestList> childTestLits, string currentTestListPath)
        {
            foreach (TestList testList in childTestLits)
            {
                if (testList.Enabled)
                {
                    string fullTestListPath = currentTestListPath == null ? string.Concat("/", testList.Name) : string.Concat(currentTestListPath,"/",testList.Name);
                    
                    AddTestCategoriesToTestLinks(testList, fullTestListPath);
                    AddCategoriesToChildPlaylists(testList.ChildLists, fullTestListPath);
                }
            }
        }

        /// <summary>
        /// Add the TestCategory attribute to all active testlinks in gevin the testlist
        /// </summary>
        /// <param name="testList">The testlist</param>
        /// <param name="fullTestListPath">The full path of the current testlist (with hierarchy)</param>
        private void AddTestCategoriesToTestLinks(TestList testList, string fullTestListPath)
        {
            foreach (TestLink testLink in testList.GetAllTestLinks())
            {
                if (testLink.Enabled)
                {
                    var test = _tmiInstance.TmiInstance.GetTest(new TestId(testLink.Id)) as TestElement;
                    test.TestCategories.Add(fullTestListPath);   
                    var properties = System.ComponentModel.TypeDescriptor.GetProperties(test);
                    var pd = properties.Find("TestCategories", false);
                    _unitTestService.UpdateTestProperty(test, pd);
                }
            }
            // Write the TestCategory attributes to code via the TMI
            _tmiInstance.SaveTestLists();
        }
    }
}
